import SparkMD5 from 'spark-md5'
import api from '@/api/index.js'

const nowStatus = { // 当前上传状态
  totalChunks: 0, // 总分片数
  fileType: '', // 文件类型
  currentChunk: 0, // 当前分片
  uploadedIdxs: [], // 已上传分片索引
  uploadJindus: [] // 已上传分片进度
}
const config = { // 上传配置
  chunkSize: 1024 * 1024 * 2, // 分片大小
  maxThreads: 2 // 最大并发数
}
const blobSlice = File.prototype.slice || File.prototype.mozSlice || File.prototype.webkitSlice

function myConsoleLog () {
  /* console.log = (function (oriLogFunc) {
		return function () {
			if (sign) {
				oriLogFunc.apply(this, arguments);
			}
		}
	})(console.log) */
  // console.log(...data)
  console.log.apply(console, arguments)
}

// 计算进度
// eslint-disable-next-line no-unused-vars
function calcProcess () {
  let jindu = 0
  for (let i = 0; i < nowStatus.uploadJindus.length; i++) {
    if (nowStatus.uploadJindus[i]) {
      jindu += nowStatus.uploadJindus[i]
    }
  }
  return Math.round(jindu / nowStatus.totalChunks)
}

function getFileMd5 (file) {
  if (!file) {
    return Promise.reject('文件不存在')
  }
  myConsoleLog('开始读取文件md5')
  return new Promise((resolve, reject) => {
    const chunks = Math.ceil(file.size / config.chunkSize)
    let currentChunk = 0
    const spark = new SparkMD5.ArrayBuffer()
    const fileReader = new FileReader()

    nowStatus.totalChunks = chunks

    fileReader.onload = function (e) {
      currentChunk++
      console.log('read chunk nr', currentChunk, 'of', chunks)
      spark.append(e.target.result) // Append array buffer
      if (currentChunk < chunks) {
        loadNext()
      } else {
        console.log('finished loading')
        resolve(spark.end())
      }
    }
    fileReader.onerror = function () {
      console.warn('oops, something went wrong.')
      reject()
    }
    function loadNext () {
      const start = currentChunk * config.chunkSize
      const end = ((start + config.chunkSize) >= file.size) ? file.size : start + config.chunkSize
      fileReader.readAsArrayBuffer(blobSlice.call(file, start, end))
    }
    loadNext()
  })
}

function checkMd5Fn (params) {
  /* return new Promise((resolve, reject) => {
		reject('未传入checkMd5Fn');
	}); */
  // TODO 改这里成自己的
  return api.system.attachment.checkMd5(params)
}

// eslint-disable-next-line no-unused-vars
function uploadChunkFn (params, config) {
  /* return new Promise((resolve, reject) => {
		reject('未传入uploadChunkFn');
	}); */
  // TODO 改这里成自己的
  return api.system.attachment.uploadChunk(params, config)
}

// eslint-disable-next-line no-unused-vars
function mergeChunkFn (params) {
  /* return new Promise((resolve, reject) => {
		reject('未传入mergeChunkFn');
	}); */
  // TODO 改这里成自己的
  return api.system.attachment.mergeChunk(params)
}

export const uploadFile = async (file, params = {}) => {
  nowStatus.uploadedIdxs.length = 0
  nowStatus.uploadJindus.length = 0
  nowStatus.currentChunk = 0
  const fileMd5 = await getFileMd5(file)
  myConsoleLog('fileMd5', fileMd5)
  const checkMd5Res = await checkMd5Fn({
    fileMd5,
    fileSize: file.size,
    fileType: file.type
  })
  myConsoleLog('checkMd5Res', checkMd5Res)
  // 21001 文件存在
  if (checkMd5Res.code === 21001) {
    return Promise.resolve(checkMd5Res)
  }
  // 21003 断点续传
  if (checkMd5Res.code === 21003) {
    // 处理已上传
    const obj = checkMd5Res.data
    const tmpUploadedIdxs = []
    Object.keys(obj).forEach(function (key) {
      // 转换成数字
      tmpUploadedIdxs.push(parseInt(obj[key]))
    })
    // 已经完成的分片，赋值进度
    for (let i = 0; i < tmpUploadedIdxs.length; i++) {
      nowStatus.uploadJindus[tmpUploadedIdxs[i]] = 100
    }
    nowStatus.uploadedIdxs = tmpUploadedIdxs
    myConsoleLog('已上传', nowStatus.uploadedIdxs)
  }
  // 21002 文件不存在
  if (checkMd5Res.code === 21002) {
    myConsoleLog('正常流程')
  }
  // 错误流程
  if (checkMd5Res.code !== 21001 && checkMd5Res.code !== 21002 && checkMd5Res.code !== 21003) {
    return Promise.reject(checkMd5Res)
  }

  return new Promise((resolve, reject) => {
    const chunkSize = config.chunkSize
    let chunkIndex = 0
    nowStatus.totalChunks = Math.ceil(file.size / chunkSize)
    const fun = function (start, end) {
      const fileReader = new FileReader()
      fileReader.onload = function (e) {
        console.log('chunkIndex', chunkIndex)
        const s = new SparkMD5.ArrayBuffer()
        s.append(e.target.result) // Append array buffer
        const pieceMd5 = s.end()
        const formData = new FormData()
        formData.append('file', new Blob([e.target.result]))
        formData.append('fileName', file.name)
        formData.append('chunks', nowStatus.totalChunks)
        formData.append('index', chunkIndex)
        formData.append('fileMd5', fileMd5)
        // formData.append('group_id', this.menuId);
        formData.append('type', file.type)
        formData.append('pieceMd5', pieceMd5)
        formData.append('fileSize', file.size)
        formData.append('lastModified', file.lastModified)
        uploadChunkFn(formData, {
          onUploadProgress: e => {
            nowStatus.uploadJindus[chunkIndex] = Math.round(e.loaded / e.total * 100)
            e.jindu = calcProcess()
            // console.log('e.jindu',e.jindu)
            if (params.onProgress) {
              params.onProgress(e)
            }
          }
        }).then(res => {
          if (res.code === 0) {
            if (chunkIndex < nowStatus.totalChunks) {
              loadNext()
              // 写入已上传index
            }
          } else {
            if (res.code === 21004) {
              // 调用合并接口
              mergeChunkFn({
                fileMd5,
                fileName: file.name,
                chunks: nowStatus.totalChunks,
                fileSize: file.size,
                lastModified: file.lastModified,
                type: file.type
                // group_id: that.menuId
              }).then(resmc => {
                resolve(resmc)
              }).catch(errmc => {
                reject(errmc)
              })
            } else {
              reject(res)
            }
          }
        }).catch((err) => {
          reject(err)
        })
      }
      fileReader.readAsArrayBuffer(blobSlice.call(file, start, end))
    }

    function loadNext () {
      const start = chunkIndex * chunkSize
      const end = ((start + chunkSize) >= file.size) ? file.size : start + chunkSize

      chunkIndex++
      if (!nowStatus.uploadedIdxs.includes(chunkIndex)) {
        fun(start, end)
      } else {
        loadNext()
      }
    }
    // loadNext();
    // 根据线程，启动
    for (let i = 1; i < config.maxThreads; i++) {
      setTimeout(() => {
        loadNext()
      }, 200)
    }
  })
}
export const setConfig = (_config) => {
  config.chunkSize = _config.chunkSize || config.chunkSize
  config.maxThreads = _config.maxThreads || config.maxThreads
}
export default {
  // 上传文件
  uploadFile (file) {
    return new Promise((resolve, reject) => {
      // 1.检查文件是否已经上传过
      this.checkMd5Fn({
        md5: file.md5,
        fileName: file.name,
        fileSize: file.size,
        fileType: file.type
      }).then(res => {
        if (res.code == 0) {
          // 2.文件已上传过
          resolve(res)
        } else {
          // 3.文件未上传过
          this.uploadFileChunk(file).then(res => {
            resolve(res)
          }).catch(err => {
            reject(err)
          })
        }
      }).catch(err => {
        reject(err)
      })
    })
  }
}
